package com.ego.receive;

import com.ego.commons.exception.DaoException;
import com.ego.commons.pojo.*;
import com.ego.commons.utils.HttpClientUtil;
import com.ego.commons.utils.IDUtils;
import com.ego.commons.utils.JsonUtils;
import com.ego.dubbo.service.TbContentDubboService;
import com.ego.dubbo.service.TbItemDubboService;
import com.ego.dubbo.service.TbOrderDubboService;
import com.ego.mail.MyMailSender;
import com.ego.pojo.*;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.*;

@Component
public class QueueListener {
    @Reference
    private TbContentDubboService tbContentDubboService;
    @Value("${ego.bigad.categoryId}")
    private Long bigadId;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Value("${ego.search.insert}")
    private String searchInsertUrl;
    @Value("${ego.search.delete}")
    private String searchDeleteUrl;
    @Value("${ego.cart.deletecarturl}")
    private String cartDeleteUrl;

    @Reference
    private TbItemDubboService tbItemDubboService;
    @Reference
    private TbOrderDubboService tbOrderDubboService;


    @Autowired
    private MyMailSender mailSender;

    // 最简单的写法，但是如果当没有发送消息时，队列没有创建，启动当前项目就会报错。
//    @RabbitListener(queues = "content")
    // 即使没有队列，也可以启动receive，自动帮助创建对垒
    @RabbitListener(bindings = {@QueueBinding(value = @Queue(name = "${ego.rabbitmq.content.queueName}"), exchange = @Exchange(name = "amq.direct"))})
    public void content(Object obj) {
        System.out.println("接收到消息：" + obj);
        /*
            redis数据同步
            1. 从mysql中取出大广告的数据
            做成Dubbo的Consumer

            2. 把数据缓存到redis中。
         */
        // 实现方案1 。把portal的consumer代码复制过来。
        List<TbContent> list = tbContentDubboService.selectAllByCategoryid(bigadId);
        List<BigAd> listBigad = new ArrayList<>();
        for (TbContent tbContent : list) {
            BigAd bigAd = new BigAd();
            bigAd.setAlt("");
            bigAd.setHeight(240);
            bigAd.setHeightB(240);
            bigAd.setHref(tbContent.getUrl());
            bigAd.setSrc(tbContent.getPic());
            bigAd.setSrcB(tbContent.getPic2());
            bigAd.setWidth(670);
            bigAd.setWidthB(550);
            listBigad.add(bigAd);
        }
        redisTemplate.opsForValue().set("com.ego.portal::bigad", JsonUtils.objectToJson(listBigad));
        // 第二种方式
        // 直接调用ego_port
//         HttpClientUtil.doGet("http://localhost:8082/bigad");
    }

    @RabbitListener(bindings = {@QueueBinding(value = @Queue(name = "${ego.rabbitmq.item.insertName}"), exchange = @Exchange(name = "amq.direct"))})
    public void itemInsert(String id) {

        System.out.println("获取到的id:" + id);
        /*
        对Solr数据的同步
         */
        Map<String, String> param = new HashMap<>();
        param.put("id", id + "");
        String result = HttpClientUtil.doPost(searchInsertUrl, param);
        System.out.println("返回的结果：" + result);
        /*
        对redis数据同步
        以后都是用这中方式编写，因为：这种方式对ego_item没有任何影响。
         */
        String[] ids = id.split(",");
        for (String idArr : ids) {
            String key = "com.ego.item::details:" + idArr;
            TbItem tbItem = tbItemDubboService.selectById(Long.parseLong(idArr));
            TbItemDetails details = new TbItemDetails();
            details.setId(tbItem.getId());
            details.setPrice(tbItem.getPrice());
            details.setSellPoint(tbItem.getSellPoint());
            details.setTitle(tbItem.getTitle());
            String img = tbItem.getImage();
            details.setImages(img != null && !img.equals("") ? img.split(",") : new String[1]);
            redisTemplate.opsForValue().set(key, details);
        }
    }

    @RabbitListener(bindings = {@QueueBinding(value = @Queue(name = "${ego.rabbitmq.item.deleteName}"), exchange = @Exchange(name = "amq.direct"))})
    public void itemDelete(String id) {
        System.out.println("delete获取到的id:" + id);
        /*
        同步Solr
         */
        Map<String, String> param = new HashMap<>();
        param.put("id", id + "");
        String result = HttpClientUtil.doPost(searchDeleteUrl, param);
        System.out.println("返回的结果：" + result);
        /*
        同步Redis
         */
        String[] ids = id.split(",");
        for (String idArr : ids) {
            String key = "com.ego.item::details:" + idArr;
            redisTemplate.delete(key);
        }
    }


    /**
     * 创建订单队列
     * <p>
     * 当接收消息带有返回值时，表示需要返回给发送方一个状态。发送方必须使用可接收状态的方法
     *
     * @param msg
     */
    @RabbitListener(bindings = {@QueueBinding(value = @Queue(name = "${ego.rabbitmq.order.createorder}"), exchange = @Exchange(name = "amq.direct"))})
    public String orderCreate(Message msg) {
        try {
            // 反序列化
            byte[] body = msg.getBody();
            InputStream is = new ByteArrayInputStream(body);
            ObjectInputStream objectInputStream = new ObjectInputStream(is);
            OrderPojo orderPojo = (OrderPojo) objectInputStream.readObject();
            // 判断库存是否足
            List<TbOrderItem> listItem = orderPojo.getOrderItems();
            for (TbOrderItem tbOrderItem : listItem) {
                TbItem tbItem = tbItemDubboService.selectById(Long.parseLong(tbOrderItem.getItemId()));
                if (tbItem.getNum() < tbOrderItem.getNum()) {
                    return null;
                }
            }
            // 执行到此处说明库存足够
            // tborder
            TbOrder tbOrder = new TbOrder();
            tbOrder.setPayment(orderPojo.getPayment());
            tbOrder.setPaymentType(orderPojo.getPaymentType());
            // 订单id
            String id = "" + IDUtils.genItemId();
            tbOrder.setOrderId(id);
            //  时间
            Date date = new Date();
            tbOrder.setCreateTime(date);
            tbOrder.setUpdateTime(date);
            // tborderitem
            for (TbOrderItem tbOrderItem : listItem) {
                tbOrderItem.setId(IDUtils.genItemId() + "");
                tbOrderItem.setOrderId(id);
            }
            // tbordershipping
            TbOrderShipping orderShipping = orderPojo.getOrderShipping();
            orderShipping.setOrderId(id);
            orderShipping.setCreated(date);
            orderShipping.setUpdated(date);

            // 插入数据
            int index = tbOrderDubboService.insert(tbOrder, listItem, orderShipping);
            if (index == 1) {
                return id;
            }
            System.out.println(orderPojo);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (DaoException e) {
            e.printStackTrace();
        }

        return null;
    }


    @RabbitListener(bindings = {@QueueBinding(value = @Queue(name = "${ego.rabbitmq.order.deletecart}"), exchange = @Exchange(name = "amq.direct"))})
    public void deleteCart(Message msg) {
        try {
            byte[] body = msg.getBody();
            InputStream is = new ByteArrayInputStream(body);
            ObjectInputStream objectInputStream = new ObjectInputStream(is);
            DeleteCartPojo deleteCartPojo = (DeleteCartPojo) objectInputStream.readObject();
            Map<String, String> param = new HashMap<>();
            param.put("userId", deleteCartPojo.getUserId() + "");
            param.put("itemId", deleteCartPojo.getItemIds());
            HttpClientUtil.doPost(cartDeleteUrl, param);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }


    // 如果rabbitmq队列中类型改变了，要删除队列重新来。
    @RabbitListener(bindings = {@QueueBinding(value = @Queue(name = "${ego.rabbitmq.mail}"), exchange = @Exchange(name = "amq.direct"))})
    public void mail(Message msg) {
        try {
            byte[] body = msg.getBody();
            InputStream is = new ByteArrayInputStream(body);
            ObjectInputStream objectInputStream = new ObjectInputStream(is);
            RabbitmqMailPojo rabbitmqMailPojo = (RabbitmqMailPojo) objectInputStream.readObject();
            mailSender.send(rabbitmqMailPojo.getEmail(),rabbitmqMailPojo.getOrderId());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}